package request

import (
	"bytes"
	"encoding/json"
	"fmt"
	"gitee.com/jn-qq/go-tools/data"
	"github.com/google/uuid"
	"github.com/mitchellh/mapstructure"
	"io"
	"maps"
	"net/http"
	"strings"
	"vector/tools"
)

// YiYuZDTask 意图诊断任务实现（模式8）
type YiYuZDTask struct {
	provinceName string
	content      string
	businessId   string
	categoryName string
	resultData   map[string]any
}

func (y *YiYuZDTask) Reset() {
	y.content = ""
	y.provinceName = ""
	y.businessId = ""
	y.categoryName = ""
	clear(y.resultData)
}

// NewTaskData 初始化任务数据
func (y *YiYuZDTask) NewTaskData(row map[string]any) error {
	y.resultData = maps.Clone(row)

	// 获取必要参数
	if provinceName, ok := row["省份"]; ok {
		y.provinceName = provinceName.(string)
	} else {
		y.resultData["备注"] = "缺少省份参数"
		return fmt.Errorf("缺少省份参数")
	}

	if content, ok := row["问题"]; ok {
		y.content = content.(string)
	} else {
		// content可以为空
		y.content = ""
	}

	if businessId, ok := row["商品ID"]; ok {
		y.businessId = businessId.(string)
	} else {
		y.resultData["备注"] = "缺少商品ID参数"
		return fmt.Errorf("缺少商品ID参数")
	}

	if categoryName, ok := row["类别"]; ok {
		y.categoryName = categoryName.(string)
	} else {
		y.resultData["备注"] = "缺少类别参数"
		return fmt.Errorf("缺少类别参数")
	}

	return nil
}

// Do 执行意图诊断任务
func (y *YiYuZDTask) Do() {
	result := map[string]any{}
	category := map[string]string{
		"套餐":    "1",
		"套餐推荐":  "1",
		"流量":    "2",
		"流量包推荐": "2",
		"权益":    "3",
		"权益推荐":  "3",
		"号卡":    "4",
		"号卡推荐":  "4",
	}

	// 省份code
	provinceCode, _ := tools.Config.Account.GetProvinceCode(y.provinceName)
	f := &functionCall{
		FunctionCode: "NGKM_SAYDIRECT_POST",
		ProvinceCode: provinceCode,
		Params: map[string]any{
			"scene":        "推荐",
			"category":     category[y.categoryName],
			"businessId":   y.businessId,
			"provinceCode": provinceCode,
		},
	}
	callResult, err := f.Request("", nil, nil)
	if err != nil {
		result["备注"] = err.Error()
	}
	if callResult != nil {
		result["function"] = callResult.String()
	} else {
		result["function"] = ""
	}

	// 将结果合并到resultData中
	for key, value := range result {
		y.resultData[key] = value
	}
}

// Result 返回任务结果
func (y *YiYuZDTask) Result() map[string]any {
	return maps.Clone(y.resultData)
}

// FAQModelTask FAQ模型任务实现（模式11）
type FAQModelTask struct {
	provinceName string
	content      string
	scene        string
	category     []string
	resultData   map[string]any
}

func (f *FAQModelTask) Reset() {
	f.provinceName = ""
	f.content = ""
	f.scene = ""
	f.category = nil
	clear(f.resultData)
}

// NewTaskData 初始化任务数据
func (f *FAQModelTask) NewTaskData(row map[string]any) error {
	f.resultData = maps.Clone(row)

	// 获取必要参数
	if provinceName, ok := row["省份"]; ok {
		f.provinceName = provinceName.(string)
	} else {
		f.resultData["备注"] = "缺少省份参数"
		return fmt.Errorf("缺少省份参数")
	}

	if content, ok := row["问题"]; ok {
		f.content = content.(string)
	} else {
		f.resultData["备注"] = "缺少问题参数"
		return fmt.Errorf("缺少问题参数")
	}

	if scene, ok := row["场景"]; ok {
		f.scene = scene.(string)
	} else {
		f.resultData["备注"] = "缺少场景参数"
		return fmt.Errorf("缺少场景参数")
	}

	if category, ok := row["分类"]; ok {
		f.category = strings.Split(category.(string), "\n")
	} else {
		f.resultData["备注"] = "缺少分类参数"
		return fmt.Errorf("缺少分类参数")
	}

	return nil
}

// Do 执行FAQ模型任务
func (f *FAQModelTask) Do() {

	// 省份code
	provinceCode, _ := tools.Config.Account.GetProvinceCode(f.provinceName)
	funcCall := &functionCall{
		FunctionCode: "NLK_NGKM_VECTORSEARCHBYKEYWORDSNEW_POST_V2",
		ProvinceCode: provinceCode,
	}

	uid := uuid.New().String()
	f.resultData["UID"] = uid

	// 构建请求负载body
	params := tools.Config.FAQ.GetBody()
	params["question"] = f.content
	params["scope"] = provinceCode
	params["questionId"] = uid
	params["questionWord"] = f.content
	params["intention"] = f.scene
	categoryIdList := tools.Config.FAQ.GetCategory(f.provinceName, f.category...)

	params["categoryId"] = categoryIdList

	header := tools.Config.FAQ.Header
	params["X-Group-Env"] = header["X-Group-Env"]
	params["x-group-env"] = header["x-group-env"]

	callResult, err := funcCall.Request("", params, header)
	if err != nil {
		f.resultData["备注"] = err.Error()
		return
	}

	type knowledge struct {
		Knowledgeunrichcontent string `json:"knowledgeunrichcontent"`
		KnowledgeName          string `json:"knowledgeName"`
		KnowledgeId            string `json:"knowledgeId"`
		GrpngList              []struct {
			GrpngId         string `json:"grpngId"`
			GrpngNm         string `json:"grpngNm"`
			Similarity      any    `json:"similarity"`
			SetRecallsource string `json:"setRecallsource"`
			AtomList        []struct {
				Unrichcontent string `json:"unrichcontent"`
				ParamName     string `json:"paramName"`
			} `json:"atomList"`
		} `json:"grpngList"`
		Similarity string `json:"similarity"`
	}

	// 提取整篇知识 和原子组
	completeKnowledge := strings.Builder{}
	atomKnowledge := strings.Builder{}
	for _, _item := range callResult.Beans() {
		var item knowledge
		err := mapstructure.Decode(_item, &item)
		if err != nil {
			f.resultData["备注"] = err.Error()
			return
		}
		if item.KnowledgeId == "" {
			continue
		}
		completeKnowledge.WriteString(item.Knowledgeunrichcontent)
		atomKnowledge.WriteString(item.KnowledgeId)
		break
		//// 整篇知识
		//if tools.Config.InterceptNum > 0 && len(item.Knowledgeunrichcontent) > tools.Config.InterceptNum {
		//	// 截取
		//	item.Knowledgeunrichcontent = item.Knowledgeunrichcontent[:tools.Config.InterceptNum]
		//}
		//completeKnowledge.WriteString(fmt.Sprintf("##TOP%d\n###知识名称：%s\n###相似性：%s\n###知识内容：%s\n", i+1, item.KnowledgeName, item.Similarity, item.Knowledgeunrichcontent))
		//
		//// 原子组
		//atomKnowledge.WriteString(fmt.Sprintf("##TOP%d\n###知识名称：%s\n", i+1, item.KnowledgeName))
		//for _, atom := range item.GrpngList {
		//	atomKnowledge.WriteString(fmt.Sprintf("###%s(%s)(%s)：", atom.GrpngNm, atom.Similarity, atom.SetRecallsource))
		//	for _, atom := range atom.AtomList {
		//		atomKnowledge.WriteString(fmt.Sprintf("%s：%s", atom.ParamName, atom.Unrichcontent))
		//	}
		//	atomKnowledge.WriteString("\n")
		//}
		//atomKnowledge.WriteString("\n")
		//completeKnowledge.WriteString("\n")
	}
	f.resultData["整篇知识"] = completeKnowledge.String()
	f.resultData["原子组"] = atomKnowledge.String()
}

// Result 返回任务结果
func (f *FAQModelTask) Result() map[string]any {
	return maps.Clone(f.resultData)
}

// functionCall 函数调用结构体
type functionCall struct {
	ProvinceCode string         `json:"provinceCode"`
	FunctionCode string         `json:"functionCode"`
	Params       map[string]any `json:"params"`
}

// Request 发送函数调用请求
func (f *functionCall) Request(url string, params map[string]any, headers map[string]string) (*functionCallResult, error) {
	if f.ProvinceCode == "" || f.FunctionCode == "" {
		return nil, fmt.Errorf("省份编码和功能编码不能为空！！！")
	}
	// 初始化请求负载body
	if params != nil {
		f.Params = params
	}
	// 初始化请求头
	if headers == nil {
		headers = map[string]string{
			"Content-Type": "application/json",
			"X-Group-Env":  "X",
			"x-group-env":  "x",
			"accesskeyid":  "56853a9f-c4be-405e-ba22-debbd3ae33c0",
		}
	}
	// 构建请求负载body
	body, err := json.Marshal(f)
	if err != nil {
		return nil, err
	}
	request, err := http.NewRequest(
		"POST",
		data.TernaryExpression(url != "", url, "https://cmkf.cmcc-cs.cn/portal/xiaohe/externalApi/function/call"),
		bytes.NewBuffer(body),
	)
	if err != nil {
		return nil, err
	}
	// 设置必要请求头
	for k, v := range headers {
		request.Header.Set(k, v)
	}
	// 发送请求
	resp, err := http.DefaultClient.Do(request)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("请求失败，状态码：%d", resp.StatusCode)
	}

	// 解析JSON数据
	body, _ = io.ReadAll(resp.Body)
	var result functionCallResult
	if err := json.Unmarshal(body, &result); err != nil {
		return nil, err
	}
	if !result.Check() {
		return &result, fmt.Errorf("请求失败，请检查参数是否正确")
	}
	return &result, nil
}

// functionCallResult 函数调用结果结构体
type functionCallResult struct {
	Objects *struct {
		Result map[string]any `json:"result,omitempty"`
	} `json:"objects,omitempty"`
	RtnMsg  string `json:"rtnMsg"`
	RtnCode string `json:"rtnCode"`
}

// String 格式化输出结果
func (f *functionCallResult) String() string {
	marshalIndent, _ := json.MarshalIndent(f, "", "\t")
	return string(marshalIndent)
}

// Check 检查结果是否有效
func (f *functionCallResult) Check() bool {
	if f.RtnCode != "0" || f.Objects == nil || f.Objects.Result == nil {
		return false
	}
	return true
}

// Beans 获取结果中的Beans字段
func (f *functionCallResult) Beans() []any {
	if beans, ok := f.Objects.Result["beans"]; ok {
		return beans.([]any)
	}
	return []any{}
}
